#ifndef __WIZ_DATATYPE_MAP_HPP__SHANHAOBO_19800429__
#define __WIZ_DATATYPE_MAP_HPP__SHANHAOBO_19800429__

#include <map>

#include "../../Base/WizBase.hpp"
#include "./WizDataTypeForEach.hpp"

#define WIZ_DECLARE_MAP(i, v)                               \
    namespace Map                                           \
    {                                                       \
    typedef ::Wiz::Map::Type<i, v>  Type;                   \
    WIZ_DECLARE(Type);                                      \
    typedef Type::tIterator         tIterator;              \
    typedef Type::tIteratorConst    tIteratorConst;         \
    typedef Type::tForEach          tForEach;               \
    typedef Type::tForEachConst     tForEachConst;          \
    typedef Type::tForEachIter      tForEachIter;           \
    }

namespace Wiz
{
    namespace Map
    {
        template< class IndexT, class ValueT, class CompT = ::std::less<IndexT> >
        struct Type : private ::std::map<IndexT, ValueT, CompT>
        {
            /////////////////////////////////////////////////////////////////////////
            typedef IndexT                                  tIndex;
            typedef const tIndex                            tIndexConst;
            WIZ_DECLARE_IO_WITHNAME(tIndex, tIndex);
            WIZ_DECLARE_REF_WITHNAME(tIndex, tIndex);

            typedef ValueT                                  tValue;
            typedef const tValue                            tValueConst;
            WIZ_DECLARE_IO_WITHNAME(tValue, tValue);
            WIZ_DECLARE_REF_WITHNAME(tValue, tValue);

            typedef CompT                                   tComp;
            WIZ_DECLARE_IO_WITHNAME(tComp, tComp);

            typedef ::std::map<tIndex, tValue, tComp>       tSuper;
            WIZ_DECLARE_IO_WITHNAME(tSuper, tSuper);

            typedef ::Wiz::Map::Type<tIndex, tValue, tComp> tThis;

            typedef typename tSuper::iterator               tSuperIterator;
            typedef typename tSuper::const_iterator         tSuperIteratorConst;
            ////////////////////////////////////////////////////////////////////////

            ////////////////////////////////////////////////////////////////////////
            typedef ::Wiz::ForEach::Type<tThis>             tForEach;
            typedef ::Wiz::ConstForEach::Type<tThis>        tForEachConst;
            typedef ::Wiz::MapForEachIter::Type<tThis>      tForEachIter;
            ////////////////////////////////////////////////////////////////////////
            struct tIterator : public tSuperIterator
            {
                tIterator()
                {

                }
                tIterator(tSuperIterator Itr) : tSuperIterator(Itr)
                {

                }
                tIndexRefConst GetIndex() const
                {
                    return (*this)->first;
                }

                tValueRef GetValue() const
                {
                    return (*this)->second;
                }
            };
            struct tIteratorConst : public tSuperIteratorConst
            {
                tIteratorConst()
                {

                }
                tIteratorConst(tSuperIteratorConst itr) : tSuperIteratorConst(itr)
                {

                }
                tIndexRefConst GetIndex() const
                {
                    return (*this)->first;
                }

                tValueRefConst GetValue() const
                {
                    return (*this)->second;
                }
            };
            //////////////////////////////////////////////////////////////////////////
		public:
			Type() : tSuper()
			{
			}
			Type(tSuper const & InSuper) : tSuper(InSuper)
			{
			}
            //////////////////////////////////////////////////////////////////////////
        public:
            tIterator Begin()
            {
                return tSuper::begin();
            }

            tIteratorConst Begin() const
            {
                return tSuper::begin();
            }

            tIterator End()
            {
                return tSuper::end();
            }

            tIteratorConst End() const
            {
                return tSuper::end();
            }

            ///-----------------------///

            ::Wiz::Size::Type Size() const
            {
                return ::Wiz::Cast::Static<::Wiz::Size::Type>(tSuper::size());
            }

            ::Wiz::Void::Type Clear()
            {
                tSuper::clear();
            }

            //////////////////////////////////
            ///
            /// itr = Begin();
            /// while (itr != End())
            /// {
            ///    /// use itr;
            ///     itr = Erase(itr);
            /// }
            ///
            //////////////////////////////////
            tIterator Erase(tIterator itr)
            {
                return tSuper::erase(itr);
            }

            ::Wiz::Bool::Type Remove(tIndexIn v)
            {
                tIterator Found = Find(v);
                if (Found == End())
                {
                    return ::Wiz::Bool::False;
                }

                Erase(Found);
                return ::Wiz::Bool::True;
            }

            tIterator Pop(tIndexIn v)
            {
                tIterator Found = Find(v);
                if (Found == End())
                {
                    return End();
                }

                return Erase(Found);
            }

            ///-----------------------///

            template<class FuncT>
            tIterator FindIf(FuncT Func)
            {
                return ::std::find_if(tSuper::begin(), tSuper::end(), Func);
            }

            template<class FuncT>
            ::Wiz::Void::Type RemoveIf(FuncT Func)
            {
                tSuper::iterator newend = ::std::remove_if(tSuper::begin(), tSuper::end(), Func);
                tSuper::erase(newend, tSuper::end());
            }

            ///-----------------------///

            tIterator Find(tIndexIn v)
            {
                return tSuper::find(v);
            }

            tIteratorConst Find(tIndexIn v) const
            {
                return tSuper::find(v);
            }

            ///-----------------------///

            ::Wiz::Bool::Type HasData(tIndexIn v) const
            {
                return tSuper::find(v) != tSuper::end();
            }

            ///-----------------------///

            ::Wiz::Bool::Type TryGet(tValueOut OutV, tIndexIn v)
            {
                tIterator Want = Find(v);
                if (Want == End())
                {
                    return ::Wiz::Bool::False;
                }

                OutV = Want.GetValue();
                return ::Wiz::Bool::True;
            }

            ValueT* TryGetPtr(tIndexIn v)
            {
                tIterator Want = Find(v);
                if (Want == End())
                {
                    return WIZ_NULLPTR;
                }

                return &(Want.GetValue());
            }

            ///-----------------------///

            tIterator Insert(tIndexIn f, tValueIn s)
            {
                return tSuper::insert(::std::pair<IndexT, ValueT>(f, s)).first;
            }

            ::Wiz::Bool::Type Insert(tIndexIn f, tValueIn s, tIterator& Itr)
            {
                ::std::pair<tIterator, ::Wiz::Bool::Type> Result = tSuper::insert(::std::pair<IndexT, ValueT>(f, s));
                Itr = Result.first;
                return Result.second;
            }

			::Wiz::Bool::Type InsertUnique(tIterator& OutItr, tIndexIn Idx, tValueIn Val)
			{
				if (this->Find(Idx) == this->End())
				{
					OutItr = this->Insert(Idx, Val);
					return ::Wiz::Bool::True;
				}
				return ::Wiz::Bool::False;
			}

            ::Wiz::Bool::Type InsertUnique(tIndexIn Idx, tValueIn Val)
            {
				tIterator DumpItr;
                return InsertUnique(DumpItr, Idx, Val);
            }

            //////////////////////////////////////////////////////////////////////////

            ::Wiz::Void::Type Merge(tThis Temp)
            {
                tForEachIter FE(Temp);

                while (FE)
                {
                    Insert(FE->GetIndex(), FE->GetValue());
                    FE++;
                }
            }
        };
    } /// end of namespace Map
} /// end of namespace Wiz

#endif /*__WIZ_DATATYPE_MAP_HPP__SHANHAOBO_19800429__*/
